package cqie.cn.frame.controller;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import cqie.cn.frame.entity.SysMenu;
import cqie.cn.frame.entity.bo.SysMenuBo;
import cqie.cn.frame.entity.qo.SysMenuQo;
import cqie.cn.frame.entity.vo.SysMenuTreeDataVo;
import cqie.cn.frame.entity.vo.SysMenuVo;
import cqie.cn.frame.service.ISysMenuService;
import cqie.cn.frame.utils.PageParam;
import cqie.cn.frame.utils.ResultVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

import static cqie.cn.frame.utils.PageParam.PAGE_NUMBER;
import static cqie.cn.frame.utils.PageParam.PAGE_SIZE;

/**
 * <p>
 * 菜单表 前端控制器
 * </p>
 *
 * @author wangLin
 * @since 2021-09-22
 */
@Api(tags = "01系统管理--02菜单管理")
@ApiModel(value = "菜单管理")
@RestController
@RequestMapping("/frame/sysMenu")
public class SysMenuController {
    @Resource
    private ISysMenuService menuService;

    //新增提交
    @ApiOperation(value = "新增提交", notes = "", response = SysMenuBo.class)
    @PostMapping(value = "/add")
    public ResultVo add(@RequestBody SysMenuBo po) {
        try {
            //1-构造mo
            SysMenu mo = new SysMenu();
            BeanUtils.copyProperties(mo, po);
            menuService.save(mo);
            //2-构造返回值
            po.setId(mo.getId());
            return ResultVo.success("新增成功！", po);
        } catch (Exception e) {
            return ResultVo.error("新增失败");
        }
    }

    //删除
    @ApiOperation(value = "删除", notes = "")
    @DeleteMapping(value = "/remove")
    public ResultVo remove(Long id) {
        try {
            menuService.removeById(id);
            return ResultVo.success("删除成功");
        } catch (Exception e) {
            return ResultVo.error(e.getMessage());
        }
    }

    //修改
    @ApiOperation(value = "修改", notes = "", response = SysMenuBo.class)
    @PutMapping(value = "/edit")
    public ResultVo edit(SysMenuBo po) {
        //获取修改前的值
        menuService.updateById(po);
        return ResultVo.success(po);
    }

    //分页列表
    @PostMapping("/listPaged")
    @ApiOperation(value = "分页列表", notes = "", response = SysMenuVo.class)
    public ResultVo listPaged(@RequestBody SysMenuQo qo) {
        try {
            Page<SysMenu> page = new Page<>(PAGE_NUMBER, PAGE_SIZE);
            //查询添加
            //1-菜单名--模糊查找
            QueryWrapper<SysMenu> wrapper = new QueryWrapper<>();
            if (!StringUtils.isEmpty(qo.getName())) {
                wrapper.like("name", qo.getName());
            }
            //2-执行分页查询
            IPage<SysMenu> datas = menuService.page(page, wrapper);
            //3-生成返回值
            // data数据中 得到集合 转成流（可以用java8的语法）遍历集合（需要的字段） 去重  转成集合
            //数据准备
            List<Long> parentIdList = datas.getRecords().stream().map(SysMenu::getParentId).distinct().collect(Collectors.toList());
            datas.getRecords().stream().filter(x -> x.getParentId() != null).map(x -> x.getParentId()).collect(Collectors.toList());
            List<SysMenu> parentMenuList = new ArrayList<>();
            if (parentIdList.size() > 0) {
                QueryWrapper<SysMenu> qwParent = new QueryWrapper<>();
                qwParent.in("id", parentIdList);
                parentMenuList = menuService.list(qwParent);
            }
            //开始映射
            for (SysMenu mo : datas.getRecords()) {
                SysMenuVo vo = new SysMenuVo();
                BeanUtils.copyProperties(mo, vo);
                //映射上级菜单
                if (mo.getParentId() != null) {
                    SysMenu findParent = parentMenuList.stream()
                            .filter(x -> x.getId().equals(mo.getParentId()))
                            .findFirst()
                            .orElse(null);
                    if (findParent != null) {
                        vo.setParentName(findParent.getName());
                    }
                }
            }
            return ResultVo.success("查询成功", null);
        } catch (Exception e) {
            return ResultVo.error(e.getMessage());
        }
    }

    //查看详情
    @ApiOperation(value = "查看详情", notes = "", response = SysMenuVo.class)
    @GetMapping(value = "/details")
    public ResultVo details(Long id) {
        try {
            //1-获取mo
            SysMenu mo = menuService.getById(id);
            if (mo == null) {
                return ResultVo.success("指定主键的编号不存在！");
            }
            //2-映射成vo
            //映射--准备
            SysMenuVo vo = new SysMenuVo();
            BeanUtils.copyProperties(mo, vo);
            //映射--上级菜单
            if (mo.getParentId() != null) {
                SysMenu parentMenu = menuService.getById(mo.getParentId());
                vo.setParentName(parentMenu.getName());
            }
            //3-返回vo
            return ResultVo.success("查看成功！", vo);
        } catch (Exception e) {
            return ResultVo.success("查看失败！");
        }
    }

    //树表结构
    @ApiOperation(value = "树形查看", notes = "", response = SysMenuVo.class)
    @GetMapping(value = "/listTreeData")
    public ResultVo listTreeData() {
        try {
            List<SysMenu> treeData = new ArrayList<>();
            List<SysMenu> all = menuService.list();
            List<SysMenu> first = all.stream().filter(x -> x.getParentId() == null).sorted(Comparator.comparing(SysMenu::getSortCode)).collect(Collectors.toList());
            for (SysMenu mo : first) {
                //添加自己和子女
                addSelfAndChildren(mo, treeData, all);
            }
            return ResultVo.success("查看成功！", treeData);
        } catch (Exception e) {
            return ResultVo.success("查看失败！");
        }
    }

    //树表结构2
    @ApiOperation(value = "树表2", notes = "构造elementUI需要的树表数据", response = SysMenuTreeDataVo.class)
    @GetMapping(value = "/listTreeData2")
    public ResultVo listTreeData2() {
        try {
            List<SysMenuTreeDataVo> ret = new ArrayList<>();
            List<SysMenu> all = menuService.list();

            List<SysMenu> first = all.stream()
                    .filter(x -> x.getParentId() == null)
                    .sorted(Comparator.comparing((SysMenu::getSortCode)))
                    .collect(Collectors.toList());

            for (SysMenu mo : first) {
                ret.add(generateTreeData(mo, all));
//                ret.add(generateTreeData(mo, ret, all));
            }
            return ResultVo.success("查看成功！", ret);
        } catch (Exception e) {
            e.printStackTrace();
            return ResultVo.error("查看失败！");

        }
    }

    /**
     * @Description: 递归方法——-添加自己及子女到树形结构
     * @Param: [mo, treeData, all]
     * @return: void
     * @Author: 王林
     * @Date: 2021/9/8
     */
    private void addSelfAndChildren(SysMenu mo, List<SysMenu> treeData, List<SysMenu> all) {
        //1-递归添加
        treeData.add(mo);
        //2-查找子女
        List<SysMenu> children = all.stream()
                .filter(x -> x.getParentId() != null && x.getParentId().equals(mo.getId()))
                .sorted(Comparator.comparing((SysMenu::getSortCode)))
                .collect(Collectors.toList());
        //3-添加子女
        for (SysMenu child : children) {
            addSelfAndChildren(child, treeData, all);
        }
    }

    /**
     * @Description: 递归方法--把SysMenu转换成SysMenuTreeData
     * @Param: [mo, treeData, all]
     * @return: void
     * @Author: 王林
     * @Date: 2021/9/9
     */
    private SysMenuTreeDataVo generateTreeData(SysMenu mo, List<SysMenu> all) {

        SysMenuTreeDataVo node = new SysMenuTreeDataVo();
        BeanUtils.copyProperties(mo, node);

        //        子菜单集合
        List<SysMenu> children = all.stream()
                .filter(x -> x.getParentId() != null && x.getParentId().equals(mo.getId()))
                .sorted(Comparator.comparing((SysMenu::getSortCode)))
                .collect(Collectors.toList());

        List<SysMenuTreeDataVo> subNodeList = new ArrayList<>();
//        把子菜单集合添加到 SysMenuTreeData的children 中
        for (SysMenu child : children) {
            subNodeList.add(generateTreeData(child, all));
        }
        node.setChildren(subNodeList);
        return node;
    }
}

